#include "gui/Button.h"

#include "utilities/Rectangle.h"

namespace gui
{
	Button::Button() : imageSet( NULL ), font( NULL )
	{
	}

	Button::Button( const gdn::Vector2f& thePos,
					const std::string& theTextIdle, const std::string& theTextHover, const std::string& theTextPress,
					const gdn::Color& theColorIdle, const gdn::Color& theColorHover, const gdn::Color& theColorPress,
					gdn::Image& theImageSet, gdn::Font& theFont, unsigned int theCharacterSize,
					const gdn::Rectanglei& theRectIdle, const gdn::Rectanglei& theRectHover, const gdn::Rectanglei& theRectPress )
	   : pos( thePos ), mousePos(),
	     textIdle( theTextIdle ), textHover( theTextHover ), textPress( theTextPress ),
	     colorIdle( theColorIdle ), colorHover( theColorHover ), colorPress( theColorPress ),
	     imageSet( &theImageSet ), font( &theFont ), characterSize( theCharacterSize ),
	     rectIdle( theRectIdle ), rectHover( theRectHover ), rectPress( theRectPress ),
		 activeRect( &rectIdle ),
		 hold( false )
	{
		buttonSprite.SetImage( *imageSet );
		buttonSprite.SetPosition( pos );
		buttonSprite.SetSubRectangle( *activeRect );

		buttonText.SetString( textIdle );
		buttonText.SetFont( *font );
		buttonText.SetColor( colorIdle );
		buttonText.SetCharacterSize( characterSize );

		gdn::Rectanglef textRect = buttonText.GetRectangle();
		gdn::Vector2< unsigned int > imageSetSize = imageSet->GetSize();

		gdn::Vector2f buttonTextPos = pos;

		buttonTextPos.x += static_cast< int >( ( ( imageSetSize.x / 3 ) - textRect.width  ) / 2 );
		buttonTextPos.y += static_cast< int >( ( ( imageSetSize.y     ) - textRect.height ) / 2 );

		//std::cout << buttonTextPos.x << " " << buttonTextPos.y << std::endl;
		//std::cout << ( ( ( imageSetSize.x / 3 ) - textRect.width  ) / 2 ) << " " << ( ( ( imageSetSize.y     ) - textRect.height ) / 2 ) << std::endl;

		buttonText.SetPosition( buttonTextPos );
	}

	int Button::Process( const gdn::Event& event )
	{
		int ret = GUI_BUTTON_IDLE;

		gdn::Vector2< unsigned int > imageSetSize = imageSet->GetSize();

		if ( event.type == gdn::Event::MouseMoved )
		{
			mousePos.x = event.x;
			mousePos.y = event.y;

			if ( util::RectangleContainsPoint< float >( gdn::Rectanglef( pos.x, pos.y, imageSetSize.x / 3, imageSetSize.y ), mousePos ) )
			{
				if ( activeRect != &rectPress )
				{
					if ( activeRect == &rectHover )
					{
						ret = GUI_BUTTON_HOVER;
					}
					else if ( activeRect == &rectIdle )
					{
						ret = GUI_BUTTON_ENTER;
					}

					activeRect = &rectHover;
					buttonSprite.SetSubRectangle( *activeRect );

					buttonText.SetColor( colorHover );
					buttonText.SetString( textHover );
				}
			}
			else
			{
				if ( activeRect == &rectHover )
				{
					ret = GUI_BUTTON_EXIT;
				}
				else
				{
					ret = GUI_BUTTON_IDLE;
				}

				activeRect = &rectIdle;
				buttonSprite.SetSubRectangle( *activeRect );

				buttonText.SetColor( colorIdle );
				buttonText.SetString( textIdle );
			}
		}
		else if ( event.type == gdn::Event::MouseButtonPressed and event.mouseButton == gdn::Mouse::Left )
		{
			if ( util::RectangleContainsPoint< float >( gdn::Rectanglef( pos.x, pos.y, imageSetSize.x / 3, imageSetSize.y ), mousePos ) )
			{
				if ( hold != true )
				{
					ret = GUI_BUTTON_HOLD;
				}
				else
				{
					ret = GUI_BUTTON_PRESS;
				}

				activeRect = &rectPress;
				buttonSprite.SetSubRectangle( *activeRect );

				buttonText.SetColor( colorPress );
				buttonText.SetString( textPress );

				hold = true;
			}
		}
		else if ( event.type == gdn::Event::MouseButtonReleased and event.mouseButton == gdn::Mouse::Left )
		{
			if ( util::RectangleContainsPoint< float >( gdn::Rectanglef( pos.x, pos.y, imageSetSize.x / 3, imageSetSize.y ), mousePos ) )
			{
				ret = GUI_BUTTON_RELEASE;

				activeRect = &rectHover;
				buttonSprite.SetSubRectangle( *activeRect );

				buttonText.SetColor( colorHover );
				buttonText.SetString( textHover );

				hold = false;
			}
		}

		return ret;
	}

	void Button::Draw( gdn::Window& window )
	{
		window.Draw( buttonSprite );
		window.Draw( buttonText );
	}

	void Button::Draw( gdn::RenderImage& renderImage )
	{
		renderImage.Draw( buttonSprite );
		renderImage.Draw( buttonText );
	}
}
